package com.team.teamuserservice.websocket;


import cn.hutool.core.lang.TypeReference;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.team.teamuserservice.annotation.WebsocketMessageType;
import com.team.teamuserservice.entity.dto.UserLocation;
import com.team.teamuserservice.entity.dto.WebsocketMessage;
import com.team.teamuserservice.entity.po.BizMerchantInfo;
import com.team.teamuserservice.service.IBizMerchantInfoService;
import com.team.teamuserservice.uitls.MessageType;
import com.team.teamuserservice.websocket.service.MessageHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class RescueWebsocketHandler extends TextWebSocketHandler {

    private final RedisTemplate<String, Object> redisTemplate;
    private final IBizMerchantInfoService merchantInfoService;

    private static final String MERCHANT_KEY = "rescueMerchant";

    //存贮加入救援的商家信息
    public static ConcurrentHashMap<Long, WebSocketSession> rescueMap = new ConcurrentHashMap<>();

    //为了通过用户id找到用户对应的session , 还需要一个用户map
    public static ConcurrentHashMap<Long, WebSocketSession> userSessionMap = new ConcurrentHashMap<>();

    //存储消息处理messageHandlerMap
    private Map<MessageType, MessageHandler> messageHandlerMap;

    //方法注入
    @Autowired
    public void setMessageHandlerMap(List<MessageHandler> messageHandlerMap){
        this.messageHandlerMap =
                messageHandlerMap.stream()
                        //过滤掉没有注解的
                        .filter(messageHandler -> messageHandler.getClass().isAnnotationPresent(WebsocketMessageType.class))
                        //收集到messageHandlerMap里面
                        .collect(Collectors.toMap(this::findUserTypeFromService, Function.identity()));

    }

    //根据策略获取策略对应的枚举类型
    private MessageType findUserTypeFromService(MessageHandler messageHandler){
        WebsocketMessageType annotation = messageHandler.getClass().getAnnotation(WebsocketMessageType.class);
        return annotation.value();
    }




    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("有人链接");
        //规定建立连接要带参数 ?merchantId=1或者?userId=2
        //从uri中获取参数
        URI uri = session.getUri();
        if (uri == null) return;

        String query = uri.getQuery();
        if (query == null) return;

        // 解析连接类型：商家连接还是用户连接
        if (query.startsWith("merchantId=")) {
            // 商家连接
            Long merchantId = parseMerchantParams(query);
            log.info("商家连接成功，商家id为：{}", merchantId);
            if (merchantId != null) {
                merchantAdd(merchantId, session);
            }
        } else if (query.startsWith("userId=")) {
            // 用户连接
            Long userId = parseUserParams(query);
            log.info("用户连接成功，用户id为：{}", userId);
            if (userId != null) {
                userSessionMap.put(userId, session);
            }
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        //解析playload
        JSONObject json = JSONUtil.parseObj(payload);
        WebsocketMessage websocketMessage = json.toBean(WebsocketMessage.class);

        JSONObject messageJson = json.getJSONObject("message");
        UserLocation userLocation = messageJson.toBean(UserLocation.class);
        websocketMessage.setMessage(userLocation); // 替换为转换后的对象

        //根据消息类型进行操作
        Enum messageType = websocketMessage.getMessageType();
        //取对应的操作的处理器
        MessageHandler messageHandler = messageHandlerMap.get(messageType);
        if (messageHandler != null) {
            //调用处理器
            messageHandler.handleMessage(session, websocketMessage);
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        URI uri = session.getUri();
        if (uri != null && uri.getQuery() != null) {
            String query = uri.getQuery();
            if (query.startsWith("merchantId=")) {
                Long merchantId = parseMerchantParams(query);
                if (merchantId != null) {
                    rescueMap.remove(merchantId);
                }
            } else if (query.startsWith("userId=")) {
                Long userId = parseUserParams(query);
                if (userId != null) {
                    userSessionMap.remove(userId);
                }
            }
        }
    }

    //解析商家参数
    private Long parseMerchantParams(String query){
        if (query != null && query.startsWith("merchantId=")){
            String idStr = query.substring("merchantId=".length());
            try {
                return Long.valueOf(idStr);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    //解析用户参数
    private Long parseUserParams(String query){
        if (query != null && query.startsWith("userId=")){
            String idStr = query.substring("userId=".length());
            try {
                return Long.valueOf(idStr);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    //商家存储到redis和对应的map
    private void merchantAdd(Long merchantId, WebSocketSession session) {
        //只会添加商户的session
        rescueMap.put(merchantId, session);
        log.info("添加map成功");
        //先查商家信息
        BizMerchantInfo merchantInfo = merchantInfoService.getById(merchantId);
        if (merchantInfo != null && merchantInfo.getLongitude() != null && merchantInfo.getLatitude() != null) {
            //之后把商家的信息存入redis和map操作
            redisTemplate.opsForGeo().add(
                    MERCHANT_KEY,
                    new Point(merchantInfo.getLongitude().doubleValue(), merchantInfo.getLatitude().doubleValue()),
                    merchantId.toString()
            );
            log.info("添加商户成功，商户id为：{}", merchantId);
        }
    }
}
